package com.ypc.user.util;

import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;

import javax.annotation.Resource;
import java.util.List;

@Component
public class RedisLock {
    @Resource
    JedisPool jedisPool;
    /**
    * @Description: 实现分布式加锁和释放锁，未考虑不同系统间不同进程出现同样hashcode的bug，如需考虑需要添加更多信息，如果是作为一个实际的运行项目，
     * 加锁时间要考虑为毫秒，否则用户等待时间可能过长。
    * @Param: [key, value, timeUnit, time] 
    * @returns: java.lang.String 
    * @Author: ypc 
    * @Date: 2021/4/12 16:43
    * @packageName: com.shop.shop.util
    */
    public String tryLock(String key, String value, String timeUnit, int time) {
        String result = jedisPool.getResource().set(key, value, "NX", timeUnit, 10);
        if ("OK".equals(result)) {
            return "OK";
        } else {
            String t = jedisPool.getResource().get(key);
            Jedis jedis = jedisPool.getResource();
            jedis.watch(key);
            if (t.split(":")[0].equals(String.valueOf(Thread.currentThread().hashCode())) || t.split(":")[1].equals("0")) {
                Transaction transaction = jedis.multi();
                String count = String.valueOf(Integer.valueOf(t.split(":")[1]) + 1);
                transaction.set(key, String.valueOf(Thread.currentThread().hashCode()) + ":" + count, "XX", timeUnit, 10);
                transaction.set(key, String.valueOf(Thread.currentThread().hashCode()) + ":" + count, "NX", timeUnit, 10);
                List<Object> lockresult = transaction.exec();
                if (lockresult != null) {
                    jedis.close();
                    return "OK";
                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            return "failed";
        }
    }

    public String tryRelease(String key){
        if (key!=null){
            Jedis jedis=jedisPool.getResource();
            jedis.watch(key);
            String[] t=jedis.get(key).split(":");
            Transaction transaction=jedis.multi();
            if (t[0].equals(String.valueOf(Thread.currentThread().hashCode())) &&
                            Integer.parseInt(t[1])>0){
                transaction.set(key,
                        t[0]+":"+String.valueOf(Integer.parseInt(t[1])-1),
                        "XX",
                        "EX",
                        10);
                List<Object> res=transaction.exec();
                if (res!=null){
                    return "OK";
                } else {
                    return "failed";
                }
            }
        }
        return "failed";
    }
}
